# -*- coding: utf-8 -*-
# Author：Penge
import os
import sys
import time
from typing import Tuple, Optional
import requests
from dotenv import load_dotenv
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
import pyfiglet
from fake_useragent import UserAgent

NETWORK_STATUS_CONNECTED = "CONNECTED"
NETWORK_STATUS_DISCONNECTED = "DISCONNECTED"
NETWORK_STATUS_OFFLINE = "OFFLINE"
NETWORK_STATUS_UNKNOWN = "UNKNOWN"
BASE_CHECK_URL = "http://172.17.2.252/"
PUBLIC_CHECK_URL = "https://www.baidu.com"
CODE_URL = "https://wlfw.ynudcc.cn/drcom/app/code.php"
LOGIN_URL = "https://weixin.ynudcc.cn/Weixin/html/drcomLogin/"
LOGIN_UA = "Mozilla/5.0 (Linux; Android 5.0; SM-N9100 Build/LRX21V) > AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 > Chrome/37.0.0.0 Mobile Safari/537.36 > MicroMessenger/6.0.2.56_r958800.520 NetType/WIFI"
console = Console()

ua: Optional[UserAgent] = None
try:
    ua = UserAgent()
except Exception:
    console.print("[yellow]警告：[/yellow] 无法初始化UA模块，将使用固定的 User-Agent 进行状态检查。")


def show_banner():
    ascii_art = pyfiglet.figlet_format("Fuck DC", font="slant")
    info_text = Text("\nVersion 1.0.0 | Author: Penge", justify="center")
    display_content = Text(ascii_art, style="bold blue") + info_text
    console.print(Panel(display_content, title="[bold yellow]滇池学院校园网自动登录[/bold yellow]",
                        subtitle="[cyan]问题联系QQ：631759716[/cyan]", border_style="green"))
    console.print()


def get_config() -> Tuple[str, int]:
    load_dotenv()
    cookie_value = os.getenv("YNUDCCWLFWID")
    check_interval_str = os.getenv("CHECK_INTERVAL")

    if not cookie_value or not check_interval_str:
        console.print(
            Panel("[bold yellow]检测到您是首次运行或配置不完整！[/bold yellow] \n现在将引导您完成基本设置。",
                  title="[cyan]配置向导[/cyan]", border_style="blue"))
        while not cookie_value:
            cookie_value = console.input("[bold cyan]请输入您的 YNUDCCWLFWID Cookie 值: [/bold cyan]").strip()
        while True:
            check_interval_str = console.input(
                "[bold cyan]请输入检查网络状态的间隔时间（秒，推荐 60）: [/bold cyan]").strip()
            if check_interval_str.isdigit() and int(check_interval_str) > 0:
                break
            else:
                console.print("[bold red]输入无效，请输入一个大于 0 的整数。[/bold red]")
        console.print("[bold green]✔ 信息收集完毕！[/bold green]")
        if console.input(
                "是否将配置保存到 `.env` 文件（下次默认）？ ([bold green]y[/bold green]/[bold red]n[/bold red]): ").lower().strip() == 'y':
            try:
                with open('.env', 'w', encoding='utf-8') as f:
                    f.write(f'YNUDCCWLFWID={cookie_value}\n')
                    f.write(f'CHECK_INTERVAL={check_interval_str}\n')
                console.print("[bold green]✔ 配置已成功保存到 .env 文件。[/bold green]")
            except IOError as e:
                console.print(f"[bold red]错误：无法写入 .env 文件: {e}[/bold red]")

    try:
        check_interval = int(check_interval_str)
    except (ValueError, TypeError):
        check_interval = 60

    console.print("\n[bold green]✔ 配置加载成功![/bold green]")
    console.print(f"  - [cyan]检查间隔:[/cyan] {check_interval} 秒")
    console.print(f"  - [cyan]YNUDCCWLFWID:[/cyan] [dim]已加载[/dim]")
    console.print("-" * 50)
    return cookie_value, check_interval


def check_public_internet() -> bool:
    try:
        requests.get(PUBLIC_CHECK_URL, timeout=5)
        return True
    except requests.RequestException:
        return False


def check_network_status() -> str:
    params = {'onlietest': '', '_': int(time.time() * 1000)}
    user_agent_string = ua.random if ua else "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    headers = {'User-Agent': user_agent_string}
    try:
        response = requests.get(BASE_CHECK_URL, params=params, headers=headers, timeout=5)
        response.raise_for_status()
        response.encoding = 'gbk'
        return NETWORK_STATUS_DISCONNECTED if "已经禁止" in response.text else NETWORK_STATUS_CONNECTED
    except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):
        return NETWORK_STATUS_OFFLINE
    except requests.exceptions.RequestException as e:
        console.print(f"[bold red]网络检查时发生未知请求错误: {e}[/bold red]")
        return NETWORK_STATUS_UNKNOWN


def perform_login(cookie: str) -> bool:
    try:
        console.print("[cyan]  -> 正在获取登录 code...[/cyan]")
        code_response = requests.get(CODE_URL, timeout=10)
        code_response.raise_for_status()
        code = code_response.text.strip()
        if not code:
            console.print("[bold red]  ❌ 登录失败: 获取到的 code 为空。[/bold red]")
            return False
        console.print(f"[green]  ✔ 已获取 code: {code}[/green]")

        console.print("[cyan]  -> 正在发送登录请求...[/cyan]")
        headers = {
            'User-Agent': LOGIN_UA,
            'Host': 'weixin.ynudcc.cn',
            'Cookie': f'YNUDCCWLFWID={cookie}'
        }
        payload = {'permit': '1', 'id': code}
        login_response = requests.post(LOGIN_URL, params={'permit': '1'}, data=payload, headers=headers, timeout=10)
        login_response.raise_for_status()
        response_text = login_response.text
        if "success" in response_text.lower():
            console.print("[bold green]  ✅ 登录成功！[/bold green]")
            return True
        else:
            console.print(f"[bold red]  ❌ 登录失败: 服务器未返回成功状态。[/bold red]")
            print(response_text)
            return False
    except requests.exceptions.RequestException as e:
        console.print(f"[bold red]  ❌ 登录过程中发生网络错误: {e}[/bold red]")
        return False


def guided_initial_login(cookie: str) -> bool:
    console.print(Panel("[bold]启动首次登录认证流程[/bold]",
                        subtitle="[cyan]请按以下步骤操作[/cyan]", border_style="magenta"))

    console.print("1. [yellow]请先连接到一个可以访问互联网的网络（例如：手机热点）。[/yellow]")
    with console.status("[cyan]正在检测公共互联网连接...[/cyan]", spinner="dots"):
        while not check_public_internet():
            time.sleep(5)
    console.print("[green]✔ 已连接到公共网络。[/green]\n")

    console.print("2. [yellow]程序将自动进行首次登录认证...[/yellow]")
    if not perform_login(cookie):
        console.print("[bold red]首次认证失败，请检查您的 Cookie 是否正确或网络是否通畅。程序无法继续。[/bold red]")
        return False
    console.print("[green]✔ 首次认证成功！[/green]\n")

    console.print("3. [yellow]请断开手机热点，然后连接回校园网（Wi-Fi 或网线）。[/yellow]")
    with console.status("[cyan]正在等待您连接到校园网...[/cyan]", spinner="dots"):
        while True:
            status = check_network_status()
            if status != NETWORK_STATUS_OFFLINE:
                break
            time.sleep(3)
    console.print("[green]✔ 已成功连接到校园网。[/green]\n")

    console.print("[bold green]引导流程完成！现在开始进入正常的网络状态监控。[/bold green]")
    console.print("-" * 50)
    return True


if __name__ == "__main__":
    show_banner()
    try:
        COOKIE, INTERVAL = get_config()
        console.print("[bold magenta]程序启动，正在检测初始网络环境...[/bold magenta]")
        initial_status = check_network_status()

        if initial_status == NETWORK_STATUS_OFFLINE:
            console.print("[yellow]提示：当前未连接到校园网，将启动首次登录引导程序。[/yellow]")
            guidance_successful = guided_initial_login(COOKIE)
            if not guidance_successful:
                sys.exit(1)
        else:
            console.print("[green]✔ 检测到已连接校园网，直接进入监控模式。[/green]\n")

        console.print("[bold magenta]开始监控网络状态...[/bold magenta]\n")
        while True:
            status = check_network_status()
            current_time = time.strftime('%Y-%m-%d %H:%M:%S')

            if status == NETWORK_STATUS_CONNECTED:
                console.print(f"[green]({current_time}) ✅ 网络状态正常，已连接到互联网。[/green]")
            elif status == NETWORK_STATUS_DISCONNECTED:
                console.print(f"[yellow]({current_time}) 🟡 检测到网络掉线，开始自动登录...[/yellow]")
                perform_login(COOKIE)
            elif status == NETWORK_STATUS_OFFLINE:
                console.print(f"[red]({current_time}) ❌ 校园网连接已断开！请重新连接校园 Wi-Fi 或网线。[/red]")
            else:
                console.print(f"[red]({current_time}) 🤔 状态未知，可能是检查接口已变更。[/red]")

            with console.status(f"[cyan]等待 {INTERVAL} 秒后进行下一次检查...[/cyan]", spinner="dots"):
                time.sleep(INTERVAL)

    except KeyboardInterrupt:
        console.print("\n\n[bold yellow]程序被用户中断，正在退出...[/bold yellow]")
        sys.exit(0)
    except Exception as e:
        console.print(f"\n\n[bold red]发生意外错误: {e}[/bold red]")
        console.print("[bold red]程序异常退出。[/bold red]")
        sys.exit(1)
